#include "tinyfsm.hpp"
#include <iostream>
#include <thread>
#include <vector>

class Node {
public:
  Node() = default;
  virtual ~Node(){};
  virtual int Init() = 0;
  virtual int Start() = 0;
  virtual int Stop() = 0;

protected:
  Status status_ = Status::Standby;
  bool is_stopping_ = false;
};

class TestNode : public Node {
public:
  TestNode() { std::cout << "hello, world" << std::endl; }
  ~TestNode() { std::cout << "goodbye, world" << std::endl; }
  int Init() override {
    std::cout << "init ok" << std::endl;
    return 0;
  }

  int Start() override {
    std::cout << "start ok" << std::endl;
    std::thread work(&TestNode::Run, this);
    workers_.push_back(std::move(work));
    return 0;
  }
  int Stop() override {
    for (auto &work : workers_) {
      work.join();
    }
    std::cout << "stop ok" << std::endl;
    return 0;
  }

private:
  void Run() {
    while (!is_stopping_) {
      std::cout << "work..." << std::endl;
      std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }
  }
  std::vector<std::thread> workers_;
};

struct StatusEvent : tinyfsm::Event {
  Status status;
};

class TestFSM : public tinyfsm::Fsm<TestFSM> {
public:
  void react(const tinyfsm::Event &e) {}
  virtual void react(const StatusEvent &e){};
  virtual void entry() { std::cout << "entry" << std::endl; };
  virtual void exit() { std::cout << "exit" << std::endl; };
};
class Off;
class Standby;
class Active;
class Passive;

class Off : public TestFSM {
  void react(const StatusEvent &e) { std::cout << "off" << std::endl; }
};

class Standby : public TestFSM {
  void react(const StatusEvent &e) {
    std::cout << "standby" << std::endl;
    if (e.status == Status::Active) {
      transit<Active>();
    }
  }
};
class Active : public TestFSM {
  void react(const StatusEvent &e) { transit<Passive>(); }
};
class Passive : public TestFSM {
  void react(const StatusEvent &e) { transit<Standby>(); }
};
FSM_INITIAL_STATE(TestFSM, Off);

int main(int argc, char *argv[]) {
  /*
TestNode *node(new TestNode);
node->Init();
node->Start();
node->Stop();
*/
  TestFSM::start();
  StatusEvent e;
  e.status = Status::Active;
  while (true) {
    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
  return 0;
}
